#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <unistd.h>
#include <string.h>
// AI回答。
// struct a {};
// 仅定义结构体类型，使用时必须带struct关键字（如struct a obj;）
// 适合不需要简化的场景，但现代C编程中较少单独使用

// typedef struct {}a;
// 匿名结构体直接通过a使用（如a obj;）
// >>>>>>>
// 简洁但无法在结构体内自引用
// 如 struct node{struct node *next;};
// 不能 struct {node *next;}node;
// 不能申明 node；但可以声明：struct node;
// <<<<<<<<<<<<<<<<<
// 适合不需要自引用的简单结构

// typedef struct a{}a;结构体标签与类型别名一样。
// 既保留结构体原名struct a，又提供别名a
// 完美支持自引用（如struct a* next;）
// 是实际开发中最推荐的写法?
// typedef struct a{}a;
// int a = 42;   // 变量名 'a' 覆盖了 typedef 别名
// // a obj3;    // 编译错误：'a' 现在是 int 而非类型
// struct a obj3; // 仍然有效
// typedef struct _a{}a;区分一下如何？



// way 1
struct StudentInformStruct1
{
    unsigned id;   // unsigned 就是 unsigned int
    char name[20]; // 用字符数组来保存名字。
};
// 这种定义结构体方式，在c编译器定义变量时，必须加struct。如下：
// c++编译时中定义变量可以不加struct。StudentInformStruct1 globalxxx;
struct StudentInformStruct1 globalStudent1;

// way 2
// 在头文件中不推荐这样用。
// 如果结构体定义放在头文件，这样定义的话，多个c文件包含了这个头文件，会报错：globalStudent2多重定义。
// 在c文件内局部调用可以这样用。
struct StudentInformStruct2
{
    unsigned id;   // unsigned 就是 unsigned int
    char name[20]; // 用字符数组来保存名字。
} globalStudent2;// globalStudent2是struct StudentInformStruct2结构体的变量。

// way 3
// StudentInformType3是struct StudentInformStruct3别名。定义变量时，可以省略struct。
typedef struct StudentInformStruct3
{
    unsigned id;   // unsigned 就是 unsigned int
    char name[20]; // 用字符数组来保存名字。
} StudentInformStruct3;
struct StudentInformStruct3 globalStudent3_1;
StudentInformStruct3 globalStudent3_2;

// way 4
// 直接不要结构体名字，用别名替换。大家可以看一下pthread.h的系统库，就是这样定义的，减少代码，定义变量时不需要加struct。
// 但这种类型不能声明，或自己嵌套使用。
/*
1.
不能这样使用：
stc2;
typedef struct
{
    stc2 *vs;
}stc1;
typedef struct
{
    int val;
}stc2;
但是下面可以：
struct stc2;
struct stc1
{
    stc2 *vs;
};
struct stc2
{
    int val;
};
2.结构体嵌套：
可以这样定义：
struct stcd
{
    struct stcd *next;
};
但不能这样定义：
typedef struct 
{
    stcd *next;
}stcd;
*/
typedef struct
{
    unsigned id;   // unsigned 就是 unsigned int
    char name[20]; // 用字符数组来保存名字。
} StudentInformType4;
StudentInformType4 globalStudent4;

// 结构体初始化。
//  {
//      struct StackInformSturct tmpstack;未初始化，随机值
//      logdebugc("%d,%d,%p", tmpstack.size, tmpstack.count, tmpstack.buffer);
//  }
//  {
//      struct StackInformSturct tmpstack = {};//内容初始化0
//      logdebugc("%d,%d,%p", tmpstack.size, tmpstack.count, tmpstack.buffer);
//  }

int main(int argc, char **argv)
{
    {
        // way 1
        struct StudentInformStruct1 tmpstudent = {1, "tmpStudent1"}; // 赋值方式1
        // 结构体变量tmpstudent自身不能直接使用，需要使用.来访问成员。
        globalStudent1.id = tmpstudent.id;
        strncpy(globalStudent1.name, "globalStudent1", sizeof(globalStudent1.name));
        printf("[%s,%d]globalStudent1.id=%u,name=%s\n", __FILE__, __LINE__, globalStudent1.id, globalStudent1.name);
        printf("[%s,%d]tmpstudent.id=%u,name=%s\n", __FILE__, __LINE__, tmpstudent.id, tmpstudent.name);
    }
    {
        // way 2
        struct StudentInformStruct2 tmpstudent = {.id = 2, .name = "tmpStudent2"}; // 赋值方式2，c99
        globalStudent2.id = tmpstudent.id;
        strncpy(globalStudent2.name, "globalStudent2", sizeof(globalStudent2.name));
        printf("[%s,%d]globalStudent2.id=%u,name=%s\n", __FILE__, __LINE__, globalStudent2.id, globalStudent2.name);
        printf("[%s,%d]tmpstudent.id=%u,name=%s\n", __FILE__, __LINE__, tmpstudent.id, tmpstudent.name);
    }
    {
        // way 3_1
        StudentInformStruct3 tmpstudent;
        tmpstudent = (StudentInformStruct3){3, "tmpStudent3"}; // 赋值方式3。不是定义的时候赋值，需要强制转换。
        globalStudent3_1.id = tmpstudent.id;
        strncpy(globalStudent3_1.name, "globalStudent3_1", sizeof(globalStudent3_1.name));
        printf("[%s,%d]globalStudent3_1.id=%u,name=%s\n", __FILE__, __LINE__, globalStudent3_1.id, globalStudent3_1.name);
        printf("[%s,%d]tmpstudent.id=%u,name=%s\n", __FILE__, __LINE__, tmpstudent.id, tmpstudent.name);
    }
    {
        // way 3_2
        struct StudentInformStruct3 tmpstudent; // 结构体未初始化，内容不确定。实际上：way3_1的局部变量释放了，这里分配的空间是way3_1的内容。
        globalStudent3_2.id = tmpstudent.id;
        strncpy(globalStudent3_2.name, "globalStudent3_2", sizeof(globalStudent3_2.name));
        printf("[%s,%d]globalStudent3_2.id=%u,name=%s\n", __FILE__, __LINE__, globalStudent3_2.id, globalStudent3_2.name);
        printf("[%s,%d]tmpstudent.id=%u,name=%s\n", __FILE__, __LINE__, tmpstudent.id, tmpstudent.name);
    }
    {
        // way 4
        StudentInformType4 tmpstudent = {}; // 赋值方式4，结构体全部成员值0.
        globalStudent4.id = tmpstudent.id;
        strncpy(globalStudent4.name, "globalStudent4", sizeof(globalStudent4.name));
        printf("[%s,%d]globalStudent4.id=%u,name=%s\n", __FILE__, __LINE__, globalStudent4.id, globalStudent4.name);
        printf("[%s,%d]tmpstudent.id=%u,name=%s\n", __FILE__, __LINE__, tmpstudent.id, tmpstudent.name);
    }
    return 1;
}
